package com.demo.java.nio;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import static com.demo.java.utils.LogUtils.log;

public class SingleThreadReactorClient {

    public static void main(String[] args) throws IOException {
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);

        SocketAddress socketAddress = new InetSocketAddress(InetAddress.getLocalHost(),7891);
//        socketChannel.bind(socketAddress);

        // connect方法要在selector.register之前，否则需要通过 finishConnect 方法判断连接是否已经创建完成，无法发送消息
//        boolean result = socketChannel.connect(socketAddress);
//        socketChannel.configureBlocking(false);

        Selector selector = Selector.open();
        socketChannel.register(selector, SelectionKey.OP_CONNECT);

        // connect方法要在selector.register之前，否则连接无法创建，无法发送消息
        boolean result = socketChannel.connect(socketAddress);

        System.out.println("connect result: " + result);
        while (selector.select() >= 0) {

            final Set<SelectionKey> selectionKeys = selector.selectedKeys();
            final Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                final SelectionKey next = iterator.next();
                iterator.remove();

                if (next.isConnectable()) {
                    // 如果Client在注册完Connection事件后发起的连接，则需要等待连接完成后才能进行数据传输
                    while (!socketChannel.finishConnect()) {
                        System.out.println("client not finish connect");
                    }
                    System.out.println("connect server success");
                    socketChannel.register(selector, SelectionKey.OP_WRITE);
                } else if (next.isWritable()) {
                    System.out.println(log("connect server"));
                    SocketChannel channel = (SocketChannel) next.channel();
//                    channel.configureBlocking(false);

                    while (!channel.isConnected()) {
                        System.out.println("not connect");
                    }

//                    ByteBuffer buffer = ByteBuffer.allocate(1024);
//                    buffer.put("hello".getBytes());
//                    buffer.flip();
//                    channel.write(buffer);

                    channel.write(ByteBuffer.wrap("hello".getBytes()));
                    channel.close();
                } else if (next.isReadable()){
                    System.out.println(log("run read from server"));
                }
            }
        }
    }
}
